//
//  jxsListViewController.m
//  ToDoList
//
// This code file is apart of project "iPhone-ToDo-List" 
// (http://code.google.com/p/iphone-todo-list/)
//
// Copyright (c) 2009 Frank Villasenor
//
// Distributed under the terms of the Lesser GNU General Public License.
// A copy of the license should be with these files. If not, you 
// can retrieve a copy from http://www.gnu.org/licenses/lgpl-3.0.txt
// 


#import "tosuTask.h"

#import "ToDoListAppDelegate.h"
#import "Constants.h"

#import "jxsTableViewCell.h"
#import "jxsListViewController.h"
#import "jxsTableViewCellController.h"
#import "jxsViewTaskDetailsViewController.h"
#import "jxsEditTaskDetailViewController.h"

#define kSecondsInOneWeek	604800


@implementation jxsListViewController

@synthesize taskList, taskListForDisplay;
@synthesize taskListTableView;
@synthesize segmentedFilter;
@synthesize viewTaskDetailsViewController, listViewController;
@synthesize currentTaskListFilter; //This doesn't need to be released...

@synthesize selectedTask;

- (void)dealloc
{
	[taskList release];
	[taskListForDisplay release];
	[taskListTableView release];
	[segmentedFilter release];
	[viewTaskDetailsViewController release];
	
	[selectedTask release];
	
    [super dealloc];
}


/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/


/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad 
{		
	//
	// Add observer so that when the app terminates, our task list
	// is saved.
	UIApplication *app = [UIApplication sharedApplication];
	[[NSNotificationCenter defaultCenter] addObserver:self
		selector:@selector(applicationWillTerminate:) 
		name:UIApplicationWillTerminateNotification 
		object:app];
	
	//
	// get a reference to the task list which
	// is now in the delegate.
	ToDoListAppDelegate *delegate = [app delegate];
	self.taskList = delegate.taskList;
	
	currentTaskListFilter = jxsTaskListFilterShowAll;
	[self setTaskListForDisplay];

	
	UIBarButtonItem *_addItem = [[UIBarButtonItem alloc] 
								 initWithBarButtonSystemItem:UIBarButtonSystemItemCompose
								 target:self 
								 action:@selector(PresentNewTaskDialog)];
	self.navigationItem.rightBarButtonItem = _addItem;
	[_addItem release];
	//[self setToolbarHidden:TRUE animated:NO];
	
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{	
	[super viewWillAppear:animated];
	
	//
	// Always reload the data.
	[self setTaskListForDisplay];
	[taskListTableView reloadData];
	
	
}

/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview

	//
	// Wanted to make this release in a memory warning condition,
	// but when I release this and do a Simulate memory warning
	// the program crashes for an unknown reason. Appears to have
	// to do with a retainCount or a partially unloaded object
	// but not yet object.
	//[self.viewTaskDetailsViewController release]; //Not essential, can be lazy loaded again.
}

#pragma mark -
#pragma mark Custom Methods

- (void)PresentNewTaskDialog
{
	NSLog( @"PresentNewTaskDialog was called." );
	
	//
	// Present the user with the dialog to create a new task.	
	jxsEditTaskDetailViewController *newTask = [[jxsEditTaskDetailViewController alloc] 
												initWithNibName:@"jxsEditTaskDetailsView"
												bundle:nil];
	
	newTask.taskToEdit = [[tosuTask alloc] init]; //create new task to edit.
	
	//
	// Show dialog as model.
	[self presentModalViewController:newTask animated:YES];

	[newTask release];
}


- (void)addTaskListTaskItem:(tosuTask *)taskToAdd
{
	if( self.taskList == nil )
	{
		[NSException raise:@"taskList Is Nil" format:@"taskList pointer is nil."];
	}
	
	if( taskToAdd != nil )
	{
		[taskList addObject:taskToAdd];
		[self updateTaskListDisplay];
	}
}

- (void)updateTaskListDisplay
{
	[self setTaskListForDisplay];
	[self.taskListTableView reloadData];
}

//
// Probably don't need this any more...
- (void)applicationWillTerminate:(NSNotification *)notification
{
	return;
}

- (IBAction)changeFilter:(id)sender
{
	NSLog( @"Calling changeFilter:" );
	NSLog(@"%i", segmentedFilter.selectedSegmentIndex);

	
	switch (segmentedFilter.selectedSegmentIndex) {
		case 0: //All
			self.currentTaskListFilter = jxsTaskListFilterShowAll;
			break;
		case 1: //Incomplete tasks.
			self.currentTaskListFilter = jxsTaskListFilterShowIncomplete;
			break;
		case 2: //Due Soon
			self.currentTaskListFilter = jxsTaskListFilterShowDueSoon;
			break;
		default:
			break;
	}
	
	[self updateTaskListDisplay];
}

//
// Create the filtered list for display; return the filtered list.
- (NSMutableArray *)createFilteredTaskListForDisplay
{
	NSMutableArray *localTaskList = nil; 
	if( self.currentTaskListFilter == jxsTaskListFilterShowAll )
	{
		//
		// Need to determine if this is a Deep or Shallow copy.
		// the main differences (pg 224) is that the Shallow is 
		// new array but "contains" points to the same objects
		// where as the Deep one is a distinct set of everything.
		// (At least for NSDictionary. Not sure if that applys to this)
		localTaskList = [self.taskList copy];
	}
	else
	{
		localTaskList = [[NSMutableArray alloc] init];
		
		for( NSInteger i = 0; i < [self.taskList count]; i++ )
		{
			tosuTask *curTask = (tosuTask *)[self.taskList objectAtIndex:i];
			
			tosuTask *taskCopy = [curTask copy];
			switch (self.currentTaskListFilter) 
			{
				case jxsTaskListFilterShowIncomplete:
					if( curTask.isComplete == NO )
					{
						[localTaskList addObject:taskCopy];
					}
					break;
					
				case jxsTaskListFilterShowDueSoon:
				{
					NSTimeInterval secondsInAWeek = kSecondsInOneWeek;
					
					NSDate *referenceDate = [[NSDate date] addTimeInterval:secondsInAWeek];
					NSComparisonResult compareResults = [curTask.dueDate compare:referenceDate];
					
					BOOL taskDueInAWeekOrLess = (compareResults == NSOrderedAscending || compareResults == NSOrderedSame);
					if( curTask.isComplete == NO && taskDueInAWeekOrLess )
					{
						[localTaskList addObject:taskCopy];
					}
					break;
				}
				default:
					break;
			}
			[taskCopy release];
		}
	}
	
	return localTaskList;

}

- (void)setTaskListForDisplay 
{
	//
	// This is done to prevent a memory leak. This is in a function
	// to prevent cut-n-paste programming.
	NSMutableArray *localTaskList = [self createFilteredTaskListForDisplay];
	self.taskListForDisplay = localTaskList;
	[localTaskList release];
}

#pragma mark -
#pragma mark UITableViewDataSource Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	//
	// Derived from the example on page 191 in Chp8.
	static NSString *TaskListIdentifier = @"jxsTableViewCellIdentifier";
	
	jxsTableViewCell *cell = (jxsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:TaskListIdentifier];
	jxsTableViewCellController *controller = nil;
	if( cell == nil )
	{
		controller = [[jxsTableViewCellController alloc] init];
		[[NSBundle mainBundle] loadNibNamed:@"jxsTableViewCell" owner:controller options:nil];
		cell = controller.cell;
	}
	else
	{
		controller = cell.controller;
	}
	
	NSInteger row = [indexPath row];
	//
	// Set Controller updates.
	controller.task = (tosuTask *)[self.taskListForDisplay objectAtIndex:row];
	
	return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	//
	// Right now, we are not using sections...
	// So, I beleive return the number of rows inside the section.
	return [self.taskListForDisplay count];
}

#pragma mark -
#pragma mark UITableViewDelegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
	NSInteger row = [indexPath row];
	selectedTask = (tosuTask *)[self.taskListForDisplay objectAtIndex:row];
	
	//
	// Create the view Controller to push on to the stack.
	if( self.viewTaskDetailsViewController == nil )
	{
		jxsViewTaskDetailsViewController *taskDetailsViewController = [[jxsViewTaskDetailsViewController alloc] 
																	   initWithNibName:@"jxsViewTaskDetailsView" 
																	   bundle:nil];
		self.viewTaskDetailsViewController = taskDetailsViewController; //Save a reference to this in the property...
		[taskDetailsViewController release];
	}
	
	self.viewTaskDetailsViewController.taskToRepresent = selectedTask;
	
	ToDoListAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
	[delegate.mainNavController pushViewController:self.viewTaskDetailsViewController animated:YES];
}



- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
	return 65; //Same value as the UITableViewCell's height inside the nib
}

#pragma mark -
#pragma mark jxsTaskReceiver Protocal Methods
- (void)UpdateLocalTaskWith:(tosuTask *)newTask
{
	//
	// Find Object and replace it.	
	NSInteger indexOfOldTaskList = -1;
	NSUInteger hash2 = [self.selectedTask hash]; //This won't change, so just calculate it now.
	
	for( NSInteger i = 0; i < [self.taskList count]; i++ )
	{
		id obj = [self.taskList objectAtIndex:i];
		if( [obj isKindOfClass:[tosuTask class]] )
		{
			tosuTask *_task = (tosuTask *)obj;
			
			NSUInteger hash1 = [_task hash];
			
			NSLog( @"_task; title = %@; hash1 = %u", _task.title, hash1 );
			NSLog( @"selectedTask; title = %@; hash2 = %u", selectedTask.title, hash2 );
			
			if( hash1 == hash2 )
			{
				indexOfOldTaskList = i;
				break;
			}
		}
	}
	
	if( indexOfOldTaskList != -1 )
	{
		//
		// Found the object to change so replace it...
		[self.taskList replaceObjectAtIndex:indexOfOldTaskList withObject:newTask];
		
		//
		// Update the task list for display (gets the new filtered list
		// and then updates the current display).
		[self updateTaskListDisplay];
		
	}
	else
	{
		[NSException raise:@"No Task" format:@"Couldn't find task."];
	}
}

- (void)addTaskWith:(tosuTask *)newTask
{
	[taskList addObject:newTask];
//	[self setTaskListForDisplay];
//	[taskListTableView reloadData];
}
@end
